package data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.joda.time.LocalDate;

import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import data.enums.Classification;
import data.enums.Continent;
import data.enums.Index;
import data.input.Data;
import entities.IndexTuple;

public class InstancesCreator {

	private LocalDate initialDate;
	private LocalDate finalDate;

	private Map<Index, Data> datasMap;

	private Iterator<List<Index>> it;

	public InstancesCreator(LocalDate initialDate, LocalDate finalDate, Map<Index, Data> datasMap, Set<List<Index>> allCombinations) {

		this.initialDate = initialDate;
		this.finalDate = finalDate;
		this.datasMap = datasMap;

		it = allCombinations.iterator();
	}

	public boolean hasNextInstances() {
		return it.hasNext();
	}

	public Instances nextInstances() throws IOException {
		return createInstances(it.next());
	}

	public Instances createInstances(List<Index> combination) throws IOException {

		FastVector classificationsTypes = new FastVector();

		for (Classification classification : Classification.values()) {
			classificationsTypes.addElement(classification.toString());
		}

		Attribute americanTrend = new Attribute("americanTrend", classificationsTypes);
		Attribute asianTrend = new Attribute("asianTrend", classificationsTypes);
		Attribute europeanTrend = new Attribute("europeanTrend", classificationsTypes);
		Attribute ibovespaTrend = new Attribute("ibovespaTrend", classificationsTypes);

		FastVector attributes = new FastVector();

		attributes.addElement(americanTrend);
		attributes.addElement(asianTrend);
		attributes.addElement(europeanTrend);
		attributes.addElement(ibovespaTrend);

		// Create an empty set of instances.
		Instances instances = new Instances(combination.toString(), attributes, 2000);

		Data data = null;
		LocalDate currentDate = initialDate;

		while (!currentDate.isEqual(finalDate)) {

			List<Classification> classifications = new ArrayList<>();

			for (Index index : combination) {

				data = datasMap.get(index);
				
				if (index.getContinent().equals(Continent.AMERICA.toString()) && index != Index.Ibovespa) {
					
					IndexTuple previousIndexTuple = data.getPreviousIndexTuple(currentDate);
					
					if(previousIndexTuple != null) {
						classifications.add(data.getPreviousIndexTuple(currentDate).getClassification());
					} else {
						break;
					}
					
				} else {
					
					IndexTuple tuple = data.getIndexTuple(currentDate);
					
					if (tuple == null) {
						break;
					}
					
					classifications.add(tuple.getClassification());
				}

			}

			if (classifications.size() == 3) {

				Instance instance = new Instance(4);

				instance.setValue(americanTrend, classifications.get(0).toString());
				instance.setValue(asianTrend, classifications.get(1).toString());
				instance.setValue(europeanTrend, classifications.get(2).toString());

				IndexTuple ibovespaTuple = datasMap.get(Index.Ibovespa).getIndexTuple(currentDate);
				if (ibovespaTuple != null) {
					instance.setValue(ibovespaTrend, ibovespaTuple.getClassification().toString());
					instances.add(instance);
				}

			}

			currentDate = currentDate.plusDays(1);
		}
		
		return instances;

	}

}
